
//
//  DataSerialize.cc
//  DataPlatform
//
//  Created by Liu Dafan on 12-2-9.
//  Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
//

#include <stdio.h>
#include <errno.h>
#include "datastream.h"
#include "base.h"

using namespace std;

DataStream::DataStream()
{
    _data = new vector<int8_t>();
    _needfree = true;
}

DataStream::DataStream(vector<int8_t>* pbdata)
{
    
    _data = pbdata;
    _needfree = false;
}


DataStream::DataStream(size_t size)
{
    _data = new vector<int8_t>(size);
    _needfree = true;
}

DataStream::~DataStream()
{
    if (_needfree)
    {
        delete _data;
    }
}

void DataStream::Serialize(const string& data)
{
    uint32_t len = data.length();
    
    Serialize(len);
    
    _data->insert(_data->end(), (const int8_t *)data.c_str(), (const int8_t *)data.c_str() + len);    
}

void DataStream::Serialize(uint32_t data)
{
    int8_t *pd = (int8_t*)&data;
    _data->insert(_data->end(), pd, pd + sizeof(int32_t));
}

void DataStream::Serialize(uint64_t data)
{
    int8_t *pd = (int8_t*)&data;
    
    _data->insert(_data->end(), pd, pd + sizeof(int64_t));
}

void DataStream::Serialize(const int8_t* data, size_t size)
{
    _data->insert(_data->end(), data, data + size);
}

void DataStream::Serialize(const FILE_DATA& data)
{
    Serialize(data._version);
    Serialize(data._fileType);
    Serialize(data._userID);
    Serialize(data._length);
    Serialize(data._dataCRC);
}

bool DataStream::UnSerialize(string& out)
{
    uint32_t len;
    bool ret = UnSerialize(len);
    
    if (!ret || _data->size() < _scanidx + len)
    {
        DERROR("Not Enough Data for unserialize: len:%d, scanidx:%d, size:%d", len, (int)_scanidx, (int)_data->size());
        return ret;
    }
    
    const char* start = (const char *)(&(*_data)[_scanidx]);
    
    out.assign(start, len);
    _scanidx += len;
    
    return ret;
}

bool DataStream::UnSerialize(uint32_t& out)
{
    size_t len = sizeof(int32_t);
    if (_scanidx + len > _data->size())
    {
        DERROR("Not Enough Data for unserialize: len:%d, scanidx:%d, size:%d", (int)len, (int)_scanidx, (int)_data->size());
        return false;
    }
    
    int8_t *pd = (int8_t*)&out;
    const int8_t *ps = &(*_data)[_scanidx];
    memcpy(pd, ps, len);
    
    _scanidx += len;
    
    return true;
}

bool DataStream::UnSerialize(uint64_t& out)
{
    size_t len = sizeof(int64_t);
    if (_scanidx + len > _data->size())
    {
        DERROR("Not Enough Data for unserialize: len:%d, scanidx:%d, size:%d", (int)len, (int)_scanidx, (int)_data->size());
        return false;
    }
    
    int8_t *pd = (int8_t*)&out;
    const int8_t *ps = &(*_data)[_scanidx];
    memcpy(pd, ps, len);
    
    _scanidx += len;

    
    return true;
}

bool DataStream::UnSerialize(int8_t*& data, size_t size)
{
    if (data != NULL)
    {
        DERROR("Input parameter Error");
        return false;
    }
    
    if (_scanidx + size > _data->size())
    {
        DERROR("Not Enough Data for unserialize: len:%d, scanidx:%d, size:%d", (int)size, (int)_scanidx, (int)_data->size());
        return false;
    }
        
    memcpy(data, &_data[_scanidx], size);
    
    _scanidx += size;
    
    return true;
}

bool DataStream::UnSerialize(FILE_DATA& data)
{
    bool ret = true;
    ret = ret && UnSerialize(data._version);
    ret = ret && UnSerialize(data._fileType);
    ret = ret && UnSerialize(data._userID);
    ret = ret && UnSerialize(data._length);
    ret = ret && UnSerialize(data._dataCRC);
    
    return ret;
}

const vector<int8_t>& DataStream::getdata()
{
    return *_data;
}
                   
void DataStream::reset()
{
    _scanidx = 0;
}

